/*
 * Copyright (c) $today.year-Now http://www.zxpnet.com All rights reserved.
 */

package com.zxp.common.core.security.filter;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.zxp.common.core.security.properties.SecurityProperties;
import com.zxp.common.core.validatecode.ValidateCodeProperties;
import com.zxp.common.core.validatecode.impl.ImageValidateCodeService;
import com.zxp.common.core.validatecode.impl.SmsValidateCodeService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
import java.util.Set;

/**
 * 验证码过滤器
 * @author: shollin
 * @date: 2021/7/6/006 11:12
 */
@Slf4j
public class ValidateCodeFilter extends OncePerRequestFilter implements InitializingBean {

    private final  RedisTemplate<String,Object> redisTemplate;

    private final AuthenticationFailureHandler failureHandler;

    private final SecurityProperties securityProperties;

    private final ImageValidateCodeService imageValidateCodeService;
    private final SmsValidateCodeService smsValidateCodeService;

    public ValidateCodeFilter(RedisTemplate<String, Object> redisTemplate,
                              AuthenticationFailureHandler failureHandler,
                              SecurityProperties securityProperties,
                              ImageValidateCodeService imageValidateCodeService,
                              SmsValidateCodeService smsValidateCodeService) {
        this.redisTemplate = redisTemplate;
        this.failureHandler = failureHandler;
        this.securityProperties = securityProperties;
        this.imageValidateCodeService = imageValidateCodeService;
        this.smsValidateCodeService = smsValidateCodeService;
    }

    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    private Set<String> imageUrls = Sets.newHashSet();
    private Set<String> smsUrls = Sets.newHashSet();

    @Override
    public void afterPropertiesSet() throws ServletException {
        super.afterPropertiesSet();

        String imgUrl = securityProperties.getCode().getImage().getUrl();
        String smsUrl = securityProperties.getCode().getSms().getUrl();

        // 图片验证码将要拦截的url进行设值
        if(StrUtil.isNotBlank(imgUrl) && ObjectUtil.isNotEmpty(imgUrl.split(",")) ){
            for (String u : imgUrl.split(",")){
                imageUrls.add(u);
            }
        }
        // 短信验证码将要拦截的url进行设值
        if(StrUtil.isNotBlank(smsUrl) && ObjectUtil.isNotEmpty(smsUrl.split(",")) ){
            for (String u : smsUrl.split(",")){
                smsUrls.add(u);
            }
        }
    }

    @SneakyThrows
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        Boolean matchURL = false;
        String uri = request.getRequestURI();


        if(antPathMatcher.match("/login",uri)){ // 图片验证码登陆

            for (String u: imageUrls) {
                if(antPathMatcher.match(u,uri)){
                    matchURL = true;
                }
            }
            if( matchURL || "POST".equalsIgnoreCase(request.getMethod()) ){
                try {
                    // 验证图片验证码
                    imageValidateCodeService.checkCode(new ServletWebRequest(request));

                }catch (org.springframework.security.core.AuthenticationException  e) {
                    log.error("图片验证码验证失败:{}",e.getMessage());
                    failureHandler.onAuthenticationFailure(request,response,e);
                    return;
                }
            }

        }else if( antPathMatcher.match("/login/mobile",uri) ){ // 手机短信验证码登陆


            for (String u: smsUrls) {
                if(antPathMatcher.match(u,uri)){
                    matchURL = true;
                }
            }
            if(matchURL || "POST".equalsIgnoreCase(request.getMethod())){
                try {
                    // 验证图片验证码
                    smsValidateCodeService.checkCode(new ServletWebRequest(request));

                }catch (org.springframework.security.core.AuthenticationException  e) {
                    log.error("手机短信验证码验证失败:{}",e.getMessage());
                    failureHandler.onAuthenticationFailure(request,response,e);
                    return;
                }
            }

        }

        // 调后边的过滤器
        filterChain.doFilter(request, response);
    }
}
